package com.jy.rhin.infra.repo.notfication.message.aspect;

import com.alibaba.fastjson.JSONObject;
import com.jy.framework.base.log.LogConstant;
import com.jy.rhin.infra.repo.notfication.message.EReceiveLogType;
import com.jy.rhin.infra.repo.notfication.message.ReceiveService;
import com.jy.rhin.infra.repo.notfication.message.TranscationMessageException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jboss.logging.MDC;
import org.springframework.amqp.core.Message;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.UUID;

/**
 * @author: yaojun
 * @Date: 2022/9/20 14:59
 * @Description: 基于spring rabbit封装的监听切面
 */
@Slf4j
@Aspect
@Component
public class RabbitListenerAspect {

    @Resource
    ReceiveService receiveService;

    @Pointcut("@annotation(org.springframework.amqp.rabbit.annotation.RabbitListener)")
    public void aspect() {
    }

    @Around("aspect()&&@annotation(receiver)")
    public void around(ProceedingJoinPoint proceedingJoinPoint, Receiver receiver) throws Throwable {
        log.debug("消息监听方法进入切面");
        long receiveTime = System.currentTimeMillis();
        Object[] args = proceedingJoinPoint.getArgs();
        Message message = null;
        Throwable throwable = null;
        try {
            message = (Message) args[0];
        } catch (Exception e) {
            log.error(TranscationMessageException.Error.ERROR_GET_ARGS.getMsg());
        }
        String messageId = "";
        JSONObject json = receiveService.getJson(message);
        if(json.containsKey("msgId")){
            messageId = json.getString("msgId");
        }else{
            messageId = UUID.randomUUID().toString().replace("-", "");
        }
        MDC.put(LogConstant.LOG_TRACE_ID, messageId);
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable t) {
            throwable = t;
            throw t;
        } finally {
            /**消费发生异常，且能获取到消息体，且注解配置错误入库*/
            if (Objects.nonNull(throwable)) {
                if (Objects.isNull(message)) {
                    log.warn("发现异常，无法获取消息体，无法做任何处理");
                } else {
                    if (EReceiveLogType.ERROR.equals(receiver.type())) {
                        if (!receiveService.exist(message)) {
                            try {
                                receiveService.addError(receiveTime, messageId, message, throwable);
                                log.debug("发现异常，记录消息日志");
                            } catch (Exception e) {
                                log.error("消费错误日志入库失败", e);
                            }
                        }
                    }
                }
            }
            log.debug("消息监听方法退出切面");
            MDC.clear();
        }
    }
}
